home *** CD-ROM | disk | FTP | other *** search
- /*
- * gradient.c
- *
- * Copyright (C) 1989, 1991, Craig E. Kolb, 1992, Lawrence Coffin
- * All rights reserved.
- *
- * This software may be freely copied, modified, and redistributed
- * provided that this copyright notice is preserved on all copies.
- *
- * You may not distribute this software, in whole or in part, as part of
- * any commercial product without the express consent of the authors.
- *
- * There is no warranty or other guarantee of fitness of this software
- * for any purpose. It is provided solely "as is".
- *
- */
-
- #include "libcommon/common.h"
- #include "libcommon/color.h"
- #include "texture.h"
- #include "gradient.h"
-
- #define sign(x) ((x) < 0 ? (-1) : (1))
-
- Gradient *
- GradientCreate(surf1, surf2, Shape, start, stop, GradType, Rand)
- Surface *surf1, *surf2;
- Float start, stop;
- int Shape, GradType, Rand;
- {
- Gradient *grad;
-
- if (start > stop){
- RLerror(RL_WARN,"Bad Gradient range\n");
- return (Gradient *)NULL;
- }
-
- grad = (Gradient *)Malloc(sizeof(Gradient));
- grad->surf1 = surf1;
- if (surf1 == surf2){
- grad->surf2 = (Surface *)NULL;
- }
- else {
- grad->surf2 = surf2;
- }
- grad->start = start;
- grad->stop = stop;
- grad->shape = Shape;
- grad->type = GradType;
- grad->rand = Rand;
-
- return grad;
-
-
- }
-
- /* Basically this texture works by calculating the distance of the point
- * "pos" according to the texture's shape. Then the distance is normalized
- * between the starting and stoping distances for the texture and changed
- * according to the gradient type. Finally, if the resulting distance
- * is between 0 and 1, the original surface is replaced with the texture's
- * first surface the blended with the second surface according to the
- * distance -- final surface = surf1*(1-dist) + surf2*dist
- */
-
- void
- GradientApply(grad,prim,ray,pos,norm,gnorm,surf)
- Gradient *grad;
- Geom *prim;
- Ray *ray;
- Vector *pos, *norm, *gnorm;
- Surface *surf;
- {
- Float len, side;
-
- /* calculate the distance of the point according to the shape */
- if (grad->shape == PLANAR){
- len = pos->z;
- side = sqrt(pos->x*pos->x + pos->y*pos->y);
- }
- else if (grad->shape == RADIAL){
- len = sqrt(pos->x*pos->x + pos->y*pos->y);
- if (pos->x != 0.0){
- side = atan(pos->y/pos->x);
- }
- else side = PI/2.0;
- }
- else if (grad->shape == SPHERICAL){
- len = sqrt(pos->x*pos->x + pos->y*pos->y + pos->z*pos->z);
-
- side = sqrt(pos->x*pos->x + pos->y*pos->y);
- if (pos->z != 0.0){
- side = atan(side/pos->z);
- }
- else side = PI/2.0;
- }
-
- /* normalize it between the start and stop distances */
- len = (len - grad->start)/(grad->stop - grad->start);
-
- /* add random noise based on the point in 3-space */
- if (grad->rand) {
- len += Noise3(pos);
- }
-
- /* modify according to Type -- linear remains the same */
- if (grad->type == LOG){
- len = sqrt(len);
- }
- else if (grad->type == REVLOG){
- len = len*len*sign(len);
- }
-
- /* check to see if the point is between 0 and 1 */
- if (len < 0 - EPSILON || len > 1 + EPSILON) {
- /* point is outside of texture range */
- return;
- }
-
-
-
- /* set surface to first surface */
- *surf = *grad->surf1;
-
- /* check to see if there is a second surface */
- if (grad->surf2 == (Surface *)NULL){
- return;
- }
-
- /* blend the two surfaces based on the length of len */
- SurfaceBlend(surf,grad->surf2,1-len,len);
- }
-
-